<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
  <title>临时文件传输</title>
  <link rel="icon" href="/images/favicon.ico" />
  <link rel="stylesheet" href="./index.css">
  <script src='./giteeApi.js'></script>
</head>

<body>
  <div class="instructions">
    <a href="https://gitee.com/zzwuweijun/learning_code/tree/master/_%E9%A1%B9%E7%9B%AE/%E6%96%87%E4%BB%B6%E4%BC%A0%E8%BE%93-%E5%88%86%E7%89%87%E4%BC%A0%E8%BE%93"
      style="text-decoration: none;">【源码】</a>
    这是个临时存储文件服务[文件切片上传]，有效期30天，具体用途，随你了~
  </div>

  <div class="main">
    <div class="inlineBlock">
      <div class="updateConten">
        <div class="updateFileConten">
          <input type="file" multiple class="file" id="updateFile">
          <div class="file-p" id="progressContent">点击上传文件 & 拖拽文件上传
            <!-- <div class="progress">
              <div class="progress_load"></div>
              <p class="progress_txt">241015_229_微信截图_20241013205609.png</p>
            </div> -->
          </div>
          <div id="againUpload">一键重新上传失败文件</div>
        </div>
      </div>
    </div>
    <div class="inlineBlock">
      <div class="showContent">
        <div class="refresh" onclick="getFiles()">
          刷新 <img src="./images/refresh.svg" id="refresh-img" class="">
        </div>
        <div class="file-content" id="files">
          <!-- <div class="file-item">
            <a href="">点击下载文件点击下载文件点击下载文件点击下载文件.txt</a>
            <div class="file-function">
              <a title="删除文件" href="" class="file-del">
                <img src="./images/delete.svg" alt="" class="myAnimation">
              </a>
              <a title="点击下载文件" href="" download class="file-dow">
                <img src="./images/dow.svg" alt="" class="myAnimation">
              </a>
              <a title="复制文件链接" href="javascript:" class="file-copy">
                <img src="./images/copy.svg" alt="" class="myAnimation">
              </a>
            </div>
          </div> -->
        </div>
      </div>
    </div>
  </div>

  <script>
    var access_token = 'bbe4ab16a0595cf7eb8399ba70766a3a'
    var owner = 'zzwuweijun02'
    var repo = 'lscc'
    geteeApi.Config.confit(access_token, owner, repo);

    let againUpload = document.getElementById('againUpload');
    let progressContent = document.getElementById('progressContent');
    let progressDiv = document.createElement('div');
    progressDiv.classList.add('progress');
    progressDiv.innerHTML = `<div class="progress_load"></div><p class="progress_txt"></p>`

    // 上传文件
    document.getElementById('updateFile').addEventListener('change', function (event) {
      var files = event.target.files;
      for (let i = 0; i < files.length; i++) {
        addRotating();
        let file = files[i];
        if (file) { setTimeout(() => { uploadFile(file) }, 1000 * (i * 0.3)); }
      }
    });

    let uploadFileErrorObj = {}; // 保存上传失败的文件信息
    // 单个文件上传
    function uploadFile(file) {
      const fileName = sanitizedAndNoDotStart(file.name)
      let d = progressDiv.cloneNode(true);
      d.querySelector('.progress_txt').innerHTML = fileName;
      progressContent.appendChild(d);

      geteeApi.tool.readAsArrayBuffer(file, function (err, base64Img) {
        if (err) { console.error(err); return; }
        geteeApi.Repositories.newFile({
          path: fileName, content: base64Img, message: "新建： " + fileName,
          onUploadProgress: function (progressEvent) { //  显示上传进度
            d.querySelector('.progress_load').style.width = Math.floor(progressEvent.progress * 100) + '%'
          },
        })
          .then(function (response) {
            if (response.status >= 200 && response.status < 300) d.remove();
            getFiles();
          })
          .catch(function (error) {
            d.querySelector('.progress_load').style.backgroundColor = '#cccccc'
            uploadFileErrorObj[fileName] = { div: d, file };
            againUpload.style.display = 'block'
          });
      })
    }

    // 点击 一键重新上传失败文件
    againUpload.onclick = function () {
      Object.keys(uploadFileErrorObj).forEach((item, index) => {
        setTimeout(() => {
          let dt = uploadFileErrorObj[item];
          dt.div.remove();
          uploadFile(dt.file);
          delete uploadFileErrorObj[item];
        }, 1000 * index);
      })
      againUpload.style.display = 'none'
    }

    // 查询所有文件
    function getFiles() {
      addRotating();
      geteeApi.Repositories.contents({ path: '/' })
        .then(function (response) {
          var { data } = response
          if (response.status >= 200 && response.status < 300) { // 判断请求是否成功

            document.getElementById("files").innerHTML = '';
            if (data.length > 0) {
              let downloadHref = location.origin + '/files/';
              data = data.reverse()
              data.forEach(element => {
                if (element.type != "file") return;
                var fileName = element.name;
                var download_url = element.download_url;
                var sha = element.sha;
                var url = element.url;
                var html_url = element.html_url;
                var download_url2 = `https://gitee.com/api/v5/repos/${owner}/${repo}/raw/${fileName}?access_token=${access_token}`;
                if (assertOverdue(fileName, sha)) return;

                var oLi = document.createElement("div");
                oLi.classList.add('file-item');
                oLi.setAttribute('data-file', fileName);
                oLi.innerHTML = `
                    <a target="_blank" href="${html_url}">${fileName}</a>
                    <div class="file-function">
                       <a title="删除文件" class="file-del myAnimation" onclick="deleteFile(this,'${fileName}', '${sha}')">
                        <img src="./images/delete.svg" alt="" class="myAnimation">
                      </a>
                      <a title="下载文件" target="_blank" href="${download_url2}" download class="file-dow myAnimation" onclick="copyFn(this,'')">
                        <img src="./images/dow.svg">
                      </a>
                      <a title="复制链接" href="javascript:" class="file-copy myAnimation" onclick="copyFn(this,'${download_url}')">
                        <img src="./images/copy.svg" class="myAnimation">
                      </a>
                    </div>`
                document.getElementById("files").appendChild(oLi).classList.remove('shake');
              });
            }
          } else {
            throw new Error(response.statusText);
            alert('获取文件发生未知错误！')
          }
          removeRotating();
        })
        .catch(function (error) {
          console.log(error);
          removeRotating();
        });
    }

    // 删除文件
    function deleteFile(event, fileName, sha) {
      let confirmed = null;
      if (event) {
        copyFn(event);
        confirmed = confirm(`确定要删除？\n\n ${fileName}`);
      }
      if (!event || confirmed) {
        geteeApi.Repositories.deleteFile({
          path: fileName,
          sha: sha,
          message: "删除 " + fileName
        }).then(json => {
          if (json.status == 200) { document.querySelector(`[data-file='${fileName}']`).remove() }
          else { alert(`删除<${fileName}>文件失败！`); }
        }).catch(function (error) {
          console.log(`删除<${fileName}>文件失败！`, error);
        });
      } else {
        console.log("用户取消删除文件。");
      }
    }

    // 判断是否过期，30天后过期
    function assertOverdue(fileName, sha) {
      let date = fileName.substr(0, 6)
      let y = date.substr(0, 2)
      let m = date.substr(2, 2)
      let d = date.substr(4, 2)
      let newDate = new Date().getTime()
      let oldDate = new Date(`20${y}-${m}-${d}`).getTime()
      let day = 1000 * 60 * 60 * 24; // 一天的秒数
      let day30 = day * 30; // 一天的秒数
      if (Math.abs(newDate - oldDate) > day30) {
        setTimeout(() => { deleteFile(null, fileName, sha) }, Math.floor(Math.random() * 30) * 1000);
        return true;
      } else return false;
    }


    window.onload = getFiles();

    function addRotating() { document.getElementById("refresh-img").classList.add('rotating'); }
    function removeRotating() { document.getElementById("refresh-img").classList.remove('rotating'); }

    // 点击一个就跳动一下
    function copyFn(event, text) {
      event.classList.add('bounce');
      // 监听动画结束事件  
      event.addEventListener('animationend', function (event) {
        if (event.animationName === 'bounce') { this.classList.remove('bounce'); }
      }, { once: true }); // { once: true } 确保事件监听器只触发一次  

      copyText(text);
    }

    // 复制文本内容
    function copyText(text) {
      let inputDom = document.createElement('input');  // 创建一个input元素
      inputDom.setAttribute('readonly', 'readonly'); // 防止手机上弹出软键盘
      inputDom.value = text; // 给input元素赋值
      document.body.appendChild(inputDom); // 添加到body
      inputDom.select(); //选中input元素的内容
      document.execCommand('Copy'); // 执行浏览器复制命令
      inputDom.style.display = 'none';
      inputDom.remove(); // 移除input元素
    }

    /**
    * 将指定日期时间或当前日期时间转换成指定的格式。
    * @fmt {String} 日期格式
    * @timestamp {Date} 标准时间。选填。
    */
    function format(fmt, timestamp) {
      const date = timestamp ? new Date(timestamp) : new Date()
      const o = {
        "Y+": date.getFullYear(), "M+": date.getMonth() + 1, "D+": date.getDate(), "h+": date.getHours(),
        "m+": date.getMinutes(), "s+": date.getSeconds(), "W": date.getDay()
      }
      for (var k in o) {
        if (new RegExp("(" + k + ")").test(fmt)) {
          fmt = fmt.replace(RegExp.$1, () => {
            if (k === 'W') { const week = ['日', '一', '二', '三', '四', '五', '六']; return week[o[k]]; }
            else if (k === 'Y+' || RegExp.$1.length == 1) { return o[k]; }
            else { return ("00" + o[k]).substr(("" + o[k]).length); }
          })
        }
      }
      return fmt
    }

    function sanitizeFilename(filename) {
      // 定义一个正则表达式，匹配不被允许的字符  
      // 这里包括了Windows中不允许的字符，以及Linux中可能不推荐的字符（如/和\）  
      // 注意：我们没有包括所有控制字符（ASCII 0-31），因为JavaScript的字符串通常不包含这些字符  
      // 也没有特别处理以点开头的文件名，因为这在很多情况下是允许的  
      const invalidCharsRegex = /[<>:"/\\|?*\r\n\&\%\*\?\+]+/gi;
      var d = new Date();
      var y = String(d.getFullYear()).substr(2);
      var m = d.getMonth() + 1;
      m = Number(m) < 10 ? '0' + m : m
      var da = d.getDate();
      da = Number(da) < 10 ? '0' + da : da
      var h = d.getHours()
      h = Number(h) < 10 ? '0' + h : h
      var min = d.getMinutes()
      min = Number(min) < 10 ? '0' + min : min

      // 使用_替换所有不被允许的字符  
      return `${y}${m}${da}_${h}${min}_` + filename.replace(invalidCharsRegex, '_');
    }
    // console.log(sanitizeFilename("file?name<with>bad:chars.txt")); // 输出: file_name_with_bad_chars.txt  

    // 如果需要特别处理以点开头的文件名（尽管这在很多系统中是允许的），可以添加额外的逻辑  
    // 例如，如果要禁止以点开头的文件名，可以添加如下判断：  
    function sanitizedAndNoDotStart(filename) {
      if (filename.startsWith('.')) {
        // 可以选择返回原始文件名、抛出错误或进行其他处理  
        // 这里我们选择添加一个下划线来避免以点开头  
        return '_' + sanitizeFilename(filename.substring(1));
      }
      return sanitizeFilename(filename);
    }
    // console.log(sanitizedAndNoDotStart(".hiddenfile.txt")); // 输出: _hiddenfile.txt
  </script>
</body>

</html>